const fs = require('fs')
const path = require('path')

const {WebSocket} = require('ws')
const CryptoJS = require('crypto-js')

class Spark {
  static APPID = ''
  static API_KEY = ''
  static API_SECRET = ''
  static HTTP_URL = new URL('https://spark-api.xf-yun.com/v1.1/chat')

  constructor() {
    this.ws = null
    this.resultData = ''
  }

  getRequestUrl() {
    let url = 'wss://' + Spark.HTTP_URL.host + Spark.HTTP_URL.pathname
    let date = new Date().toGMTString()
    let headers = 'host date request-line'
    let signature = CryptoJS.enc.Base64.stringify(
      CryptoJS.HmacSHA256(
        `host: ${Spark.HTTP_URL.host}\ndate: ${date}\nGET ${Spark.HTTP_URL.pathname} HTTP/1.1`,
        Spark.API_SECRET
      )
    )
    let authorization = btoa(
      `api_key="${Spark.API_KEY}", algorithm="hmac-sha256", headers="${headers}", signature="${signature}"`
    )
    return `${url}?authorization=${authorization}&date=${date}&host=${Spark.HTTP_URL.host}`
  }

  sendMessage(content) {
    this.ws.send(
      JSON.stringify({
        header: {
          app_id: Spark.APPID,
          uid: 'lisys'
        },
        parameter: {
          chat: {
            domain: 'general',
            temperature: 0.5,
            max_tokens: 512
          }
        },
        payload: {
          message: {
            text: [
              {
                role: 'user',
                content: `你是一个软件大师，我将提供软件名称，你需要用简短的语言进行描述它的作用，官网链接地址，然后将这个软件所属的分类进行逗号分隔出来，格式案例如下：
              
                        软件名称：
                        软件作用：
                        官网地址：
                        分类标签：
              
                        接下来我会给你提供对应的软件名称，你按照上述格式进行回答，如软件7z2107-x64`
              },
              {
                role: 'assistant',
                content: `软件名称：7z2107-x64
                      软件作用：7z2107-x64 是一种文件压缩和解压缩工具，它能够提供高压缩比和强大的加密功能。
                      官网地址：https://www.7-zip.org/
                      分类标签：压缩工具， 文件管理， 开源软件`
              },
              {role: 'user', content: content}
            ]
          }
        }
      })
    )
  }

  chat(content, onGetResult) {
    this.ws = new WebSocket(this.getRequestUrl())

    this.ws.on('open', () => {
      this.sendMessage(content)
    })

    this.ws.on('message', (content) => {
      let data = JSON.parse(content)
      let code = data['header']['code']
      if (code === 0) {
        let choices = data['payload']['choices']
        let status = choices['status']
        this.resultData += choices['text'][0]['content']
        if (status === 2) {
          this.ws.close()
        }
      } else {
        this.ws.close()
      }
    })

    this.ws.on('close', () => {
      onGetResult(this.resultData)
    })
  }

  chatPromise(content) {
    return new Promise((resolve) => {
      this.chat(content, (resultData) => {
        resolve(resultData)
      })
    })
  }
}

async function questionAppInfo(appName) {
  return await new Spark().chatPromise(appName)
}

async function main() {
  let dirs = fs.readdirSync('Y:\\resources\\tools\\Windows\\工具')
  let apps = dirs.filter((item) => !item.startsWith('.')).map((item) => path.parse(item).name)
  let appInfos = []

  for (let app of apps) {
    let appInfo = {
      name: app,
      info: ''
    }
    console.log(`询问：${app}`)
    appInfo.info = await questionAppInfo(app)
    console.log(`回答：${appInfo.info}`)
    appInfos.push(appInfo)
  }

  fs.writeFileSync('app.json', JSON.stringify(appInfos))
}

main()
